﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;
using DocumentFormat.OpenXml.Drawing.Wordprocessing;
using System.IO;

namespace DocumentService
{
    public class DocumentService : IDisposable
    {
        private WordprocessingDocument document;
        private string path;
        private string tempPath;
        public List<Exception> Exceptions { get; private set; }
        public DocumentService(string filePath)
        {
            Exceptions = new List<Exception>();
            var index = filePath.LastIndexOf('.');
            tempPath = filePath.Insert(index,"_temp");
            path = filePath;
            System.IO.File.Copy(path, tempPath, true);
            document = WordprocessingDocument.Open(tempPath, true);


        }

        /// <summary>
        /// Get image from title
        /// </summary>
        /// <param name="field">Image title.</param>
        /// <returns>success state</returns>
        public bool AccessImage(string field, string newFilePath)
        {
            try
            {
                var property = document.MainDocumentPart.Document.Body.Descendants<DocumentFormat.OpenXml.Drawing.Wordprocessing.DocProperties>().Where(x => x.Title == field);

                var imageId = property.Single().Parent.Descendants<DocumentFormat.OpenXml.Drawing.Blip>().First().Embed;

                var imagePart = (ImagePart)document.MainDocumentPart.GetPartById(imageId);

                byte[] imageBytes = File.ReadAllBytes(newFilePath);
                BinaryWriter writer = new BinaryWriter(imagePart.GetStream());
                writer.Write(imageBytes);
                writer.Close();
                return true;
            }
            catch (Exception e)
            {
                Exceptions.Add(e);
                return false;
            }
        }

        /// <summary>
        /// Verifie the existens of a given field
        /// </summary>
        /// <param name="field">The field name</param>
        /// <returns></returns>
        public bool VerifyField(string field)
        {
            try
            {
                var property = document.MainDocumentPart.Document.Body.Descendants<DocumentFormat.OpenXml.Drawing.Wordprocessing.DocProperties>().Where(x => x.Title == field).ToList();

                var alias = document.MainDocumentPart.Document.Descendants<SdtAlias>().SingleOrDefault(x => x.Val.Value == field);

                if (alias == null && property == null) return false;

                return true;
            }
            catch (Exception e)
            {
                Exceptions.Add(e);
                return false;
            }
        }

        public bool TextToField(string field, string text)
        {
            try
            {
                var alias = document.MainDocumentPart.Document.Descendants<SdtAlias>().SingleOrDefault(x => x.Val.Value == field);

                if (alias == null) return false;

                var sdt = alias.Ancestors<SdtElement>().Single();
                var paragraph = sdt.Descendants<Paragraph>().SingleOrDefault();
                var properties = paragraph.Descendants<RunProperties>().Last();

                properties.RemoveAllChildren<Languages>();
                paragraph.RemoveAllChildren<Run>();
                var run = paragraph.AppendChild(new Run());

                run.AppendChild(new Text(text));
                run.AppendChild(properties.CloneNode(true));

                document.MainDocumentPart.Document.Save();
                return true;
            }
            catch (Exception e)
            {
                Exceptions.Add(e);
                return false;
            }
        }

        public void Dispose()
        {
            document.Dispose();
        }
    }
}
